/*
 *-----------------------------------------------------------------
 *	 INCLUDE
 *-----------------------------------------------------------------
 */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "common.h"

extern int 	seed;
extern CTYPE	ortcell[HOW_MANY_TYPES];

void errorMsg(char error_text[])
{
  fprintf(stderr, "My Run-time error...\n");
  fprintf(stderr, "%s\n",error_text);
  fprintf(stderr, "...now exiting to system...\n");
  exit(0);
}

void save_ps_header(FILE *fp, int np)
{
	
  fprintf(fp,"%%!PS-Adobe-2.0 EPSF-2.0\n"); /* ps header */
  /*fprintf(fp,"%%%%BoundingBox: 0 0 612 792\n");*/
  fprintf(fp,"%%%%Author: Marcelo Walter - output from the CM program (marcelow@cs.ubc.ca)\n");
  fprintf(fp,"%%%%BoundingBox: 0 0 300 300\n");
  fprintf(fp,"%%%%EndComments\n\n\n");
  
  /* definition for a circle */
  fprintf(fp,"/d { %% definition of a circle\n");
  fprintf(fp,"gsave\n");
  fprintf(fp,"0 setgray\n");
  fprintf(fp,"0 setlinewidth\n");
  fprintf(fp,"/beadr exch def\n");
  fprintf(fp,"/yloc exch def\n");
  fprintf(fp,"/xloc exch def\n\n");
  fprintf(fp,"newpath\n");
  fprintf(fp,"xloc yloc moveto\n");
  fprintf(fp,"xloc yloc beadr 0 360 arc\n");
  fprintf(fp,"fill\n");
  fprintf(fp,"grestore\n");
  fprintf(fp,"} def\n\n");
  
  /* definition of a procedure to draw faces as filled polygons */
  fprintf(fp,"/f { %% Definition of a procedure to draw faces as filled polygons\n");
  fprintf(fp,"  /nvert exch def\n");	
  fprintf(fp,"  newpath\n\n");
  fprintf(fp,"  vert\n");
  fprintf(fp,"  moveto\n\n");
  fprintf(fp,"  2 1 nvert {pop vert lineto} for\n");
  fprintf(fp,"  closepath\n");
  fprintf(fp,"  gsave fill grestore\n");
  fprintf(fp,"  border\n");
  fprintf(fp,"} def\n\n");

  /* definition of a procedure to draw faces as empty polygons */
  fprintf(fp,"%% Definition of a procedure to draw borders\n\n");
  fprintf(fp,"/border {gsave 0 setlinewidth 0 setgray stroke grestore} def\n");

  /* definition of a procedure to acess the vertices array */
  fprintf(fp,"/vert { %% Definition of a procedure to acess the vertices array\n");
  fprintf(fp,"  dup\n");
  fprintf(fp,"  x exch get\n");
  fprintf(fp,"  exch\n");
  fprintf(fp,"  y exch get\n");
  fprintf(fp,"} def\n\n");

  /* definition of a procedure to draw in yellow rgb*/
  fprintf(fp,"/w { %% Definition of a procedure to paint C cells\n");
  fprintf(fp,"  %1.3f\n",(float)ortcell[C].color[R]/255.0);
  fprintf(fp,"  %1.3f\n",(float)ortcell[C].color[G]/255.0);
  fprintf(fp,"  %1.3f\n",(float)ortcell[C].color[B]/255.0); 
  fprintf(fp,"  setrgbcolor\n"); 
  fprintf(fp,"} def\n\n");

  /* definition of a procedure to paint D cells */
  fprintf(fp,"/b {%% Definition of a procedure to paint D cells\n");
  fprintf(fp,"  %1.3f\n",(float)ortcell[D].color[R]/255.0);
  fprintf(fp,"  %1.3f\n",(float)ortcell[D].color[G]/255.0);
  fprintf(fp,"  %1.3f\n",(float)ortcell[D].color[B]/255.0);
  fprintf(fp,"  setrgbcolor\n");
  fprintf(fp,"} def\n\n");

  /* definition of a procedure to paint E cells */
  fprintf(fp,"/u {%% Definition of a procedure to paint E cells\n");
  fprintf(fp,"  %1.3f\n",(float)ortcell[E].color[R]/255.0);
  fprintf(fp,"  %1.3f\n",(float)ortcell[E].color[G]/255.0);
  fprintf(fp,"  %1.3f\n",(float)ortcell[E].color[B]/255.0);
  fprintf(fp,"  setrgbcolor\n");
  fprintf(fp,"} def\n\n");

  fprintf(fp,"/h {%% Definition of a procedure to draw 6-sided polygon\n");
  fprintf(fp," 6\n");
  fprintf(fp," f\n");
  fprintf(fp,"} def\n");

  fprintf(fp,"/i {%% Definition of a procedure to draw 7-sided polygon\n");
  fprintf(fp," 7\n");
  fprintf(fp," f\n");
  fprintf(fp,"} def\n");

  fprintf(fp,"/m {%% Definition of a procedure to draw light gray\n");
  fprintf(fp,"  0.8 setgray\n");
  fprintf(fp,"} def\n");

  fprintf(fp,"/n {%% Definition of a procedure to draw medium gray\n");
  fprintf(fp,"  0.6 setgray\n");
  fprintf(fp,"} def\n");

  fprintf(fp,"/o {%% Definition of a procedure to draw dark gray\n");
  fprintf(fp,"  0.4 setgray\n");
  fprintf(fp,"} def\n");

  fprintf(fp,"%% npoints = %d\n\n",np);
  /*fprintf(fp,"100 150 translate\n");*/
  fprintf(fp,"1.5 1.5 scale\n\n");
  fprintf(fp,"0 setlinewidth\n\n");
}

/*
 *--------------------------------------------------------------
 * Returns a float in the range (min,max) with
 * uniform distribution
 *--------------------------------------------------------------
 */
double fran(double min, double max)
{
  
  return(min + ran1(&seed)*(max-min));

}

/*
 *--------------------------------------------------------------
 * Returns a int in the range (min,max) with
 * uniform distribution
 *--------------------------------------------------------------
 */
int iran(int min, int max)
{
  
  return(min + ran1(&seed)*(max-min));
}

/*
 *------------------------------------------------------------
 * 	Random distribution suggested by Mark
 *	less variation than a Poisson distribution
 *------------------------------------------------------------
 */
int mypoidev(float xm,int *idum)
{
  float x;

  x = ran1(&seed);
  if ( x < .33) return floor(xm-1.0);
  else if ( x < .66) return floor(xm);
  else return floor(xm+1.0);
}

/*
 * ANSI C code from the article
 * "Centroid of a Polygon"
 * by Gerard Bashein and Paul R. Detmer,
 * (gb@locke.hs.washington.edu, pdetmer@u.washington.edu)
 * in "Graphics Gems IV", Academic Press, 1994
 */

/************************************************************************
  polyCentroid: Calculates the centroid (xCentroid, yCentroid) and area
  of a polygon, given its vertices (x[0], y[0]) ... (x[n-1], y[n-1]). It
  is assumed that the contour is closed, i.e., that the vertex following
  (x[n-1], y[n-1]) is (x[0], y[0]).  The algebraic sign of the area is
  positive for counterclockwise ordering of vertices in x-y plane;
  otherwise negative.

  Returned values:  0 for normal execution;  1 if the polygon is
  degenerate (number of vertices < 3);  and 2 if area = 0 (and the
  centroid is undefined).
************************************************************************/
int polyCentroid(double x[], double y[], int n,
		 double *xCentroid, double *yCentroid, double *area)
{
  register int i, j;
  double ai, atmp = 0, xtmp = 0, ytmp = 0;

  if (n < 3) return 1;

  for (i = n-1, j = 0; j < n; i = j, j++){
    ai = x[i] * y[j] - x[j] * y[i];
    atmp += ai;
    xtmp += (x[j] + x[i]) * ai;
    ytmp += (y[j] + y[i]) * ai;
  }
  *area = atmp / 2;
  if (atmp != 0){
    *xCentroid = xtmp / (3 * atmp);
    *yCentroid = ytmp / (3 * atmp);
    return 0;
  }
  return 2;
}
